﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Com.FastSearch.SharePoint.Interfaces;
using Com.FastSearch.SharePoint.WebControls.ESPSearchWebParts.UI.Client;
using Com.FastSearch.SharePoint.WebControls.ESPSearchWebParts.UI.Editors;

namespace Com.FastSearch.SharePoint.WebControls.ESPSearchWebParts.UI
{
    /// <summary>
    /// ESPSearchConfig is used to configure all necessary and some optional parameters used to access the search server
    /// and perform a search.<br/>
    /// The necessary properties are:
    /// <code>
    /// ESPConnection: The qrserver connection(s)
    /// SearchView: The search view used for the search.
    /// </code>
    /// All other properties are "optional" in the way that they are not necessary to do a search 
    /// but still make sense to have unified in one web part.<br/>
    /// Also having those properties set to a value gives the advantage that one does not have to know what the 
    /// default value in the Search Server might be if a search is done.<br/>    
    /// <br/>   
    /// All custom properties are configured using a Custom Property editor. See <see cref="ESPSearchConfigEditorPart"/>
    /// <br/>   
    /// See <see cref="ESPSearchWebPart"/> for detailed information on the Search lifecycle.
    ///    
    /// </summary>
    public class ESPSearchConfig : ESPSearchWebPart
    {
        #region Private variables
        /// <summary>
        /// Default view used if the web part is added to a page.
        /// </summary>
        private const string DEFAULT_VIEW = "espsystemwebcluster";
        #endregion

        #region Constructor
        /// <summary>
        /// Configures the search web part with the default search settings.<br/>
        /// Set the default view, query template, number of reslts returned 
        /// and the url query parameter name.
        /// </summary>
        public ESPSearchConfig()
        {
            // Configure defaults for search
            NumberOfResults = 10;
            URLQueryParameter =
                Com.FastSearch.SharePoint.WebControls.ESPSearchWebParts.UI.Client.SearchRequest.DEFAULT_QUERY_PROPERTY_NAME;
            QueryTemplate = ESPSearchConfigEditorPart.QUERY_TEMPLATE_SIMPLEALL;
            SearchView = DEFAULT_VIEW;
            DefaultQuery = "";
        }

        #endregion
              
        #region WebPart Properties
       

        /// <summary>
        /// Turn on/off the synonyms on query time
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public Boolean SynonymFeature
        {
            get; //{ return synonymFeature; }
            set; // { synonymFeature = value; }
        }

        /// <summary>
        /// Turn on/off the Lemmatization on query time.
        /// <b>Node:</b>Content must either be indexed with lemmatization enabled or query side lemmatization must be configured.
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public Boolean LemmatizationFeature
        {
            get;
            set;
        }

        /// <summary>
        /// Configuration of the spellcheck feature which can be one of 
        /// "auto", "off", "suggest"
        /// For more info onhte Spellcheck Feature consult the ESP Configuration Documentation.        
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string SpellcheckFeature
        {
            get; //{ return spellcheckFeature; }
            set; //{spellcheckFeature = value;}
        }
        
        /// <summary>
        /// configure the search view in which the search shall be performed
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string SearchView
        {
            get;
            set;
        }
        
        /// <summary>
        /// Specify the number of results which shall be returned from the search server per search page
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public int NumberOfResults
        {
            get;
            set;
        }

        /// <summary>
        /// Specify the default sorting which shall be used for the search
        /// This can be any sorteable field or rank profile        
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string ResultSorting
        {
            get;
            set;
        }

        /// <summary>
        /// Query Template used to perform the search.
        /// <code>
        /// content:string("{0}", mode="SIMPLEANY", annotation_class="{1}")
        /// </code>        
        /// where as {0} will be replaced with the query parameters and {1} will be replaced with the string "user".                
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string QueryTemplate
        {
            get;
            set;
        }

        /// <summary>
        /// Add static query properties which shall be sent to the search server
        /// </summary>
        [Category(_CATEGORY_STR),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string StaticQueryProperties
        {
            get;
            set;
        }

        /// <summary>
        /// Specify the Query Parameter.<br/>
        /// By default the k parameter is used as in the default sharepoint search.<br/>
        /// Can be changed in the <see cref="ESPSearchConfigEditorPart"/> if the search group is NOT group0
        /// </summary>
        [Category(_CATEGORY_STR), 
        DefaultValue(Com.FastSearch.SharePoint.WebControls.ESPSearchWebParts.UI.Client.SearchRequest.DEFAULT_QUERY_PROPERTY_NAME), 
        Personalizable(PersonalizationScope.Shared), WebBrowsable(false)]
        public string URLQueryParameter
        {
            get;
            set;
        }

        /// <summary>
        /// The ESP QRServer connection(s) string used to connect to the search service.
        /// This custom property is by default configured on a web application level.
        /// Can be overwritten for each search group if needed in the Web Prt Editor. <see cref="ESPSearchConfigEditorPart"/>
        /// </summary>
        [Category(_CATEGORY_STR),DefaultValue("ESPConnection"),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string ESPConnection
        {
            get;
            set;
        }

        [Category(_CATEGORY_STR),DefaultValue(""),Personalizable(PersonalizationScope.Shared),WebBrowsable(false)]
        public string DefaultQuery
        {
            get;
            set;
        }
        
        
        #endregion             

        #region Custom Editor Registering

        /// <summary>
        /// Register the Custom Editor used to configure the custom properties
        /// </summary>
        /// <returns>Collection of default editor parts plus the custome Editor. See: <see cref="EditorPartCollection"/> </returns>
        public override EditorPartCollection CreateEditorParts()
        {
            List<EditorPart> customEditorPartCollection = new List<EditorPart>();
            ESPSearchConfigEditorPart configEditor = new ESPSearchConfigEditorPart(_CATEGORY_STR);
            configEditor.ID = "ESPSearchConfigEditorPart" + ESPSearchGroupID;
            configEditor.Title = _CATEGORY_STR;
            customEditorPartCollection.Add(configEditor);
            EditorPartCollection editorPartCollection = new EditorPartCollection(customEditorPartCollection);
            return editorPartCollection;
        }

        #endregion     

        #region Desing Time Web part configuration Display

        /// <summary>
        /// Write a config line (Table row)
        /// </summary>
        /// <param name="writer"><see cref="HtmlTextWriter"/></param>
        /// <param name="label">Custom Property Name</param>
        /// <param name="config">Custom Property Value</param>
        private static void WriteConfigLine(HtmlTextWriter writer, string label, int config)
        {
            WriteConfigLine(writer, label, config.ToString());
        }

        /// <summary>
        /// Write a config line (Table row)
        /// </summary>
        /// <param name="writer"><see cref="HtmlTextWriter"/></param>
        /// <param name="label">Custom Property Name</param>
        /// <param name="config">Custom Property Value</param>
        private static void WriteConfigLine(HtmlTextWriter writer, string label, Boolean config)
        {
            WriteConfigLine(writer, label, config.ToString());
        }

        /// <summary>
        /// Write a config line (Table row)
        /// </summary>
        /// <param name="writer"><see cref="HtmlTextWriter"/></param>
        /// <param name="label">Custom Property Name</param>
        /// <param name="config">Custom Property Value</param>
        private static void WriteConfigLine(HtmlTextWriter writer, string label, string config)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.Write(label + " :");
            writer.RenderEndTag();
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.Write("<b>" + config + "</b>");
            writer.RenderEndTag();
            writer.RenderEndTag();
        }

        /// <summary>
        /// Write the design time web part configuration to the web part for easier 
        /// configuration overview
        /// </summary>
        /// <param name="writer"><see cref="HtmlTextWriter"/></param>
        protected override void WriteWebPartDesingModeInfo(HtmlTextWriter writer)
        {
            base.WriteWebPartDesingModeInfo(writer);

            Title = string.Format("{0} Zone: {1}", Title, ESPSearchGroupID);

            //writer.Write("The following information is only visible at design time.<br/>");

            writer.Write("<h3>ESP Search Configuration for Search Group (" + ESPSearchGroupID + "):</h3> ");
            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            WriteConfigLine(writer, "Cross WebPart ID<b>", ESPSearchGroupID.ToString());
            WriteConfigLine(writer, "Search View", SearchView);
            WriteConfigLine(writer, "Pages Per Page", NumberOfResults);
            WriteConfigLine(writer, "Sorting", ResultSorting);
            WriteConfigLine(writer, "Synonyms", SynonymFeature);
            WriteConfigLine(writer, "Lemmatization", LemmatizationFeature);
            WriteConfigLine(writer, "Spellcheck", SpellcheckFeature);
            WriteConfigLine(writer, "Query Template", QueryTemplate);
            WriteConfigLine(writer, "Static Query Parameter", StaticQueryProperties);
            WriteConfigLine(writer, "URL Query Parameter", URLQueryParameter);
            WriteConfigLine(writer, "Default Query Parameter", DefaultQuery);
            WriteConfigLine(writer, "QRServer Connection(s)", ESPConnection);

            writer.RenderEndTag();
            writer.WriteBreak();
        }

        #endregion

        #region ESPSearchWebPart overrides

        /// <summary>
        /// Add the Web Part custom properties which are search specific to the <see cref="SearchRequest"/><br/>
        /// See <see cref="ESPSearchWebPart.ConfigureSearch"/> for details.
        /// </summary>
        protected override void ConfigureSearch()
        {
            SearchRequest.NumberOfResultsPerPage = NumberOfResults;
            SearchRequest.ESPSearchView = SearchView;
            SearchRequest.LemmatizationEnabled = LemmatizationFeature.ToString();
            SearchRequest.Spellcheck = SpellcheckFeature;
            SearchRequest.ResultSorting = ResultSorting;
            SearchRequest.SynonymsEnabled = SynonymFeature.ToString();
            SearchRequest.QueryTemplate = QueryTemplate;
            SearchRequest.StaticCustomQueryProperties = StaticQueryProperties;
            SearchRequest.QueryURLPropertyName = URLQueryParameter;
            SearchRequest.ESPConnection = ESPConnection;

            if (!String.IsNullOrEmpty(SearchRequest.WeightedSearchQuery))
            {
                SearchRequest.SetCustomParameterByName("XRANK", SearchRequest.WeightedSearchQuery);
            }

            if (DefaultQuery != null)
            {
                SearchRequest.SetCustomParameterByName("defaultQuery", DefaultQuery);
            }
        }

        /// <summary>
        /// Refresh the <see cref="SearchRequest"/> if the configuration chanaged in the Web Part Editor.
        /// </summary>
        public void ConfigurationChanged()
        {
            ConfigureSearch();
        }
              
        /// <summary>
        /// See <see cref="ESPSearchWebPart.SetSearchResult"/>
        /// </summary>
        /// <param name="SearchResult"><see cref="IESPSearchResult"/> object containing all result information</param>
        public override void SetSearchResult(IESPSearchResult SearchResult)
        {
            // Nothing to be done here
        }
        #endregion
    }
}